package cn.xzqwjw.taskmanager.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.xzqwjw.taskmanager.common.customEnum.ResponseCodeEnum;
import cn.xzqwjw.taskmanager.common.exception.CustomException;
import cn.xzqwjw.taskmanager.domain.pojo.Category;
import cn.xzqwjw.taskmanager.domain.pojo.SysFrontRoute;
import cn.xzqwjw.taskmanager.domain.vo.ResponseVo;
import cn.xzqwjw.taskmanager.repository.CategoryMapper;
import cn.xzqwjw.taskmanager.utils.JsonUtil;
import cn.xzqwjw.taskmanager.utils.MyListUtil;
import cn.xzqwjw.taskmanager.utils.MyStringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.xzqwjw.taskmanager.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author rush
 */
@EnableTransactionManagement
@Service("CategoryService")
@Slf4j
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

  private final CategoryMapper categoryMapper;

  @Autowired
  public CategoryServiceImpl(CategoryMapper categoryMapper) {
    this.categoryMapper = categoryMapper;
  }

  // ==================== 通用CRUD ====================

  @Override
  public String add(Category category) {
    if (save(category)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_CREATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_INSERT);
    }
  }

  @Transactional
  @Override
  public String addBatch(String tag, int idParent, String rows) {
    // QueryWrapper<Category> wrapper = new QueryWrapper<>();
    // 先清空某tag下所有非系统内置的子分类，只留下根目录和系统内置的栏目
    // wrapper.eq("flag_system", 0)
    //        .eq("tag", tag)
    //        .eq("id_parent", idParent)
    //        .gt("id", 1);
    //    remove(wrapper);
    // 遍历每行，添加多个类别
    // String[] categorys = rows.split(System.lineSeparator());
    String[] categorys = rows.split("\n");
    categorys = MyStringUtil.clearEmptyValue(categorys);
    if (ArrayUtil.isEmpty(categorys)) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    Category category;
    int startDepth = getDepthByIdParent(idParent);
    int depth;
    for (String row : categorys) {
      category = new Category();
      category.setTag(tag);
      category.setLabel(row.trim());
      // 根据本行最前面空格数设置本行的深度
      depth = getDepthBySpaceCount(row, startDepth);
      if (depth > startDepth + 1) {
        // 如果当前深度大于起始深度，说明是选定父栏目的子栏目下的孙栏目
        // 查询得到上一深度的id，即为本行的父id
        category.setIdParent(getIdParentByDepth(depth, tag));
      } else {
        // 否则当前深度等于起始深度，说明是选定父栏目的子栏目
        category.setIdParent(idParent);
      }
      category.setDepth(depth);
      save(category);
    }
    return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_CREATED));
  }

  @Override
  public String delById(int id) {
    // 先判断有没有子分类
    QueryWrapper<Category> wrapper = new QueryWrapper<>();
    wrapper.eq("id_parent", id);
    if (count(wrapper) > 0) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
    // 删除非系统内置的类别
    wrapper = new QueryWrapper<>();
    wrapper.eq("id", id).eq("flag_system", 0);
    if (remove(wrapper)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_DELETED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_DELETE);
    }
  }

  @Override
  public String modify(Category category) {
    if (updateById(category)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_UPDATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_UPDATE);
    }
  }

  @Override
  @Transactional(readOnly = true)
  public String queryById(int id) {
    return JsonUtil.obj2Json(ResponseVo.success(getById(id)));
  }

  /**
   * 如果有标签，则根据标签得到所有分类列表
   * 如果无，则到所有分类列表
   */
  @Override
  public String listAll(String tag) {
    if (StringUtils.hasText(tag)) {
      QueryWrapper<Category> wrapper = new QueryWrapper<>();
      wrapper.eq("tag", tag);
      return JsonUtil.obj2Json(ResponseVo.success(list(wrapper)));
    } else {
      return JsonUtil.obj2Json(ResponseVo.success(list()));
    }
  }

  @Override
  public List<Integer> listAllIdSub() {
    QueryWrapper<Category> wrapper = new QueryWrapper<>();
    wrapper.eq("tag", "部门单位").orderByAsc("id");
    List<Category> resultList = list(wrapper);
    List<Integer> allIdList = new ArrayList<>();
    getChildCategoryList(106, resultList, allIdList);
    MyListUtil.clearRepeat(allIdList);
    return allIdList;
  }

  /**
   * 获取某子部门的所有上级id，包括父id，爷id，用于编辑时，设置树的展开
   */
  @Override
  public List<Integer> listAllIdParent(int id) {
    List<Integer> allIdList = new ArrayList<>();
    allIdList.add(id);
    listIdParent(id, allIdList);
    return allIdList;
  }

  // ==================== 私有函数 ====================

  /**
   * 根据本行最前面的空格数得到深度
   */
  private int getDepthBySpaceCount(String row, int startDepth) {
    int startIndex = 0;
    // 首先获取第一个非空格字符的下标
    for (int i = 0; i < row.toCharArray().length; i++) {
      if (' ' != row.toCharArray()[i]) {
        startIndex = i;
        break;
      }
    }
    // 然后计算第一个非空格字符前的空格数
    int spaceNum = 0;
    for (int i = 0; i < startIndex; i++) {
      spaceNum += 1;
    }
    // 取余运算符是“%”符号，表示将左侧操作数除以右侧操作数的余数。例如，7%2的结果是1
    spaceNum = spaceNum % 2 > 0 ? spaceNum - 1 : spaceNum;
    // 整数除法的结果是一个整数，即只保留除法的整数部分，舍去小数部分
    // 例如，7/2的结果是3，而不是3.5
    return spaceNum / 2 + startDepth + 1;
  }

  /***
   * 根据本行深度获取父id
   */
  private int getIdParentByDepth(int depth, String tag) {
    depth = depth - 1;
    QueryWrapper<Category> wrapper = new QueryWrapper<>();
    wrapper.select("id")
        .eq("depth", depth)
        .eq("tag", tag)
        .orderByDesc("id")
        .last("limit 1");
    Map<String, Object> resultMap = getMap(wrapper);
    if (MapUtils.isEmpty(resultMap)) {
      return 0;
    } else {
      return (int) resultMap.get("id");
    }
  }

  /***
   * 根据父id获取深度
   */
  private int getDepthByIdParent(int idParent) {
    QueryWrapper<Category> wrapper = new QueryWrapper<>();
    wrapper.select("depth").eq("id", idParent);
    Map<String, Object> resultMap = getMap(wrapper);
    if (MapUtils.isEmpty(resultMap)) {
      return 0;
    } else {
      return (int) resultMap.get("depth");
    }
  }

  /***
   * 根据父id获取此父id下所有子id及所有孙id，并存到allIdList中
   */
  private void getChildCategoryList(Integer idParent, List<Category> rootCategoryList, List<Integer> allIdList) {
    // 得到某id下的所有子类别
    List<Category> childCategoryList = new ArrayList<>();
    allIdList.add(idParent);
    for (Category category : rootCategoryList) {
      // 遍历所有节点，将父id与传过来的id比较，从而将所有子类别放到 childCategoryList 中
      if (category.getIdParent().equals(idParent)) {
        childCategoryList.add(category);
      }
    }
    // 递归退出条件
    if (childCategoryList.isEmpty()) {
      return;
    }
    for (Category category : childCategoryList) {
      allIdList.add(category.getId());
      getChildCategoryList(category.getId(), rootCategoryList, allIdList);
    }
  }

  /***
   * 根据id获取此id所有父id及爷id，并存到allIdList中
   */
  private void listIdParent(int id, List<Integer> allIdList) {
    int idParent = getIdParent(id);
    allIdList.add(idParent);
    if (idParent > 0) {
      listIdParent(idParent, allIdList);
    }
  }

  private int getIdParent(int id) {
    QueryWrapper<Category> wrapper = new QueryWrapper<>();
    wrapper.select("id_parent").eq("id", id);
    Map<String, Object> returnMap = getMap(wrapper);
    return MapUtils.isEmpty(returnMap) ? 0 : (int) returnMap.get("id_parent");
  }

}




